/*
TimeLine object
A data driven timeline chart
-Requires: jQuery 1.1+ library, see jQuery.com for details
-Requires: my date methods, see date.js
-Author: John Snook 2007
*/

/*
* Timeline object contructor
* container should be a jquery object, and settings is an json object
*/
function Timeline(container, settings)
{
	this._dateUnits = new Array( 'minute', 'hour', 'day', 'month', 'year', 'decade', 'century', 'millenium');
	this._monthnames = Array("January","February","March","April","May", "June","July","August","September","October","November","December");
	this.dateUnit = this._dateUnits.indexOf(settings.dateUnit);
	this.startDate = settings.startDate;
	this.endDate = settings.endDate;
	this.smallColumnWidth = (settings.smallColumnWidth) ? settings.smallColumnWidth : 16;
	this.rowsBoxTop = (settings.rowsBoxTop) ? settings.rowsBoxTop: 44;
	container.append('<div id="control"><div id="columnsBox"></div><div id="rowsBox"></div></div>');
	this.control = $("#control", container);
	var basicCss = {
		position:"absolute",
		left: '0px',
		top:'0px',
		bottom: '0px'
	};
	// create the rowsBox and columnsBox inside the container and get a jquery reference
	this.control.css($.extend(basicCss, {
		width: settings.width ? settings.width : "100%"
	}));
	
	// the columns and items are drawn on the rowsBox
	this.columnsBox = $('#columnsBox', this.control).css($.extend(basicCss, { width: 'auto'	}));
	
	// the rows and items are drawn on the rowsBox
	this.rowsBox = $('#rowsBox', this.control).css($.extend(basicCss, {
		top: this.rowsBoxTop + 'px',
		width: '100%'
	}));
	
	// figure out how wide each dateUnit and smallerUnit is
	$("#debug").append("this.rowsBox.width(): "+ this.rowsBox.width() +"<br />");
	$("#debug").append(+"<br />");

	return this;
}

Timeline.prototype =
{
	getColumnOffset: function(date)
	{
		var dateUnitMedium = this._dateUnits[this.dateUnit];
		var dateUnitSmall = this._dateUnits[this.dateUnit - 1];
		var id = "#" + dateUnitMedium + '-' + date.getByPartName(dateUnitMedium);
		var smallid = "#" + dateUnitSmall + '-' + date.getByPartName(dateUnitSmall);
		var left = $(id + ' ' + smallid, this.columnsBox).offset().left;
		return left;
	},
	renderColumns: function()
	{
		var incDate = new Date(0);
		var L = M = S = LBox = MBox = SBox = null;
		var adjustedHeight = 0;
		var dateUnitLarge = this._dateUnits[this.dateUnit + 1];
		var dateUnitMedium = this._dateUnits[this.dateUnit];
		var incPart = dateUnitSmall = this._dateUnits[this.dateUnit - 1];
		incDate.setTime(this.startDate.getTime());
		$("#debug").append('incDate.getByPartName(this._dateUnits[this.dateUnit])' + incDate.getByPartName(this._dateUnits[this.dateUnit]) + "<br />");
		this.control.parent().css({overflow: 'hidden'});
		this.columnsBox.width(31000);

		while (incDate.getByPartName(this._dateUnits[this.dateUnit]) <= this.endDate.getByPartName(this._dateUnits[this.dateUnit]))
		{
			if(this.dateUnit != this._dateUnits.length) // do we have a larger dateUnit?
			{
				value = incDate.getByPartName(dateUnitLarge);
				if(L != value)
				{
					id = dateUnitLarge + '-' + value;
					this.columnsBox.append('<div id="' + id + '" class="largeColumn">' + incDate.getByPartName(dateUnitLarge, true) + '</div>');
					LBox = $('#' + id, this.columnsBox).css({float: 'left'});
//					$("#debug").append('LBox.offset().top: ' + LBox.offset().top + '<br />');
				}
				L = value;
			}
			else
			{
				LBox = this.columnsBox;
			}
			value = incDate.getByPartName(dateUnitMedium);
			if(M != value)
			{
				id = dateUnitMedium + '-' + value;
				LBox.append('<div id="' + id + '" class="mediumColumn"></div>');
				MBox = $('#' + id, LBox).css({float: 'left'}).append(incDate.getByPartName(dateUnitMedium, true));
				adjustedHeight = LBox.height() - (MBox.offset().top - LBox.offset().top);
				if( adjustedHeight ==0 ) adjustedHeight = LBox.height() - (MBox.offset().top - LBox.offset().top);
				MBox.height(adjustedHeight);
			}
			M = value;
			if(this.dateUnit != 0) // do we have a smaller dateUnit?
			{
				value = incDate.getByPartName(dateUnitSmall);
				if(S != value)
				{
					id = dateUnitSmall + '-' + value;
					MBox.append('<div id="' + id + '" class="smallColumn">' + incDate.getByPartName(dateUnitSmall, true) + '</div>');
					SBox = $('#' + id, MBox).css({
						float: 'left',
						width:'15px',
						textAlign:'center'
					});
					if( adjustedHeight ==0) adjustedHeight = LBox.height() - (SBox.offset().top - LBox.offset().top);
					SBox.height(adjustedHeight);
					//SBox.css({bottom: SBox.offset().top - LBox.offset().top + 'px'});
				}
				//$("#debug").append('SBox.css("bottom"): ' + SBox.css("bottom") + '<br />');
				S = value;
			}
			else
			{
				incPart = dateUnitMedium
			}
			incDate.addByPartName(incPart, 1);
		}
		$("#debug").append('incDate.getByPartName(this._dateUnits[this.dateUnit])' + incDate.getByPartName(this._dateUnits[this.dateUnit]) + "<br />");
		var totalwidth = 0;
		
		$('.largeColumn', this.columnsBox).each(function()
		{
			totalwidth += $(this).width();
			//$("#debug").append('totalwidth: ' + totalwidth + '<br />');
		});
		$("#debug").append('totalwidth: ' + totalwidth +"<br />");
		this.columnsBox.width(totalwidth);
		this.rowsBox.width(totalwidth);
		this.control.parent().css({overflow: 'auto'});
		$("#debug").append('this.columnsBox.width(): ' + this.columnsBox.width() +"<br />");
		// All this crap below is to get the auto scrolling container to snap to the new size
		//$('div', this.columnsBox).css({bottom: '0px'});

		return this;
	},
	/*
	*	addRow - Adds an row div to the rowsBox div and returns a jQuery reference to the added row.
	*   Expects something like:
		{
			id: 2,
			caption: 'Philosophy'
		}
	*/
	addRow: function(args)
	{
		this.rowsBox.append('<div id="row-' + args.id + '" class="row"><span class="caption">' + args.caption + '</span></div>');
		row = $("#" + args.id, this.rowsBox).css({
			width:"100%"
		});
		var totalheight = 0;
		$('.row', this.rowsBox).each(function()
		{
			totalheight += $(this).height();
		});
//		this.rowsBox.height(totalheight);
		// below we set the row to a percentage 
		var pctH = Math.round(100 / $('.row', this.rowsBox).length) + '%';
		return $('.row', this.rowsBox).css({height: pctH});
	},

	/*
	*	addItem - Adds an item div to the specified row and returns a jQuery reference.
	*   Expects something like:
		{
			id: 6,
			row: 1,
			startDate: new Date("Jan 1, 1960"),
			endDate: new Date("Dec 31, 1969") 
		}
	*/
	addItem: function(obj)
	{
		var container = (obj.row) ? $('#row-' + obj.row, this.rowsBox) : this.rowsBox;
		container.append('<div class="item" id="item-'+ obj.id +'"></div>');
		var right = left = this.getColumnOffset(obj.startDate);
		if(obj.endDate)
			var right = this.getColumnOffset(obj.endDate);
		//$("#debug").append('+(getColumnOffset) offset: ' + offset +"<br />");

		return $('div#item-' + obj.id, container).css({
			position: 'absolute',
			left: (left - this.control.offset().left - 5) + 'px',
			width: (right - left + 5) + 'px'
		});
	}
};